#include "world.hpp"

#include "resourcehandler.hpp"
#include "exception.hpp"
#include "stringutil.hpp"
#include "fileutil.hpp"
#include "roomblueprint.hpp"
#include "roomhandler.hpp"
#include <fstream>

namespace nmc
{
    World* World::mInstance = 0;

    World* World::getInstance()
    {
        if (mInstance == 0)
        {
            mInstance = new World();
        }

        return mInstance;
    }

    World::World()
    {
        load();
    }

    int World::getRoomAt(int x, int y)
    {
		for (unsigned int i = 0; i < mRoomBlueprints.size(); i++)
		{
			RoomBlueprint *r = mRoomBlueprints[i];
			if (x >= r->getWorldX() &&
				x < r->getWidth() + r->getWorldX() &&
                y >= r->getWorldY() &&
				y < r->getHeight() + r->getWorldY())
            {
                return i;
            }
        }
       
        throw NMC_EXCEPTION("No room found at coordinate (" + toString(x) + "," + toString(y) + ").");
    }

	RoomBlueprint *World::getRoomBlueprint(int index)
	{
		return mRoomBlueprints.at(index);
	}

    void World::save()
    {
        std::ofstream file(ResourceHandler::getInstance()->getRealFilename("world.dat").c_str(), 
                           std::ios_base::out | std::ios_base::binary);

		if (!file.is_open() || !file.good())
		{
			file.close();
			throw NMC_EXCEPTION("Unable to open " 
                + ResourceHandler::getInstance()->getRealFilename("world.dat") + " for writing.");
		}

        writeInt(file, mRoomBlueprints.size());

		for (unsigned int i = 0; i < mRoomBlueprints.size(); i++)
		{          
            writeString(file, mRoomBlueprints[i]->getFilename());
        }

        file.close();
    }

    void World::load()
    {
        std::ifstream file(ResourceHandler::getInstance()->getRealFilename("world.dat").c_str(),
                           std::ios_base::in | std::ios_base::binary);
	
		mRoomBlueprints.clear();

		if (!file.is_open() || !file.good())
		{
			file.close();
	        return;
		}

		int size = readInt(file);
		int i;
		for (i = 0; i < size; i++)
		{
			std::string filename = readString(file);
			mRoomBlueprints.push_back(RoomHandler::getInstance()->getRoomBlueprint(filename));
		}

		file.close();
    }

	bool World::isEmpty()
	{
		return mRoomBlueprints.empty();
	}
}